package com.hedl.practice.diyJava.reflex.study_01;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;

public class ObjectAnalyzer {
    private ArrayList<Object> visited = new ArrayList<>();

    public String toString(Object obj){
        if (obj == null){
            return "null";
        }
        if (visited.contains(obj)){     //如果该对象已经处理过，则不再处理
            return "...";
        }
        visited.add(obj);

        Class c = obj.getClass();
        if (c == String.class){     //如果是String类型则直接转为String
            return (String) obj;
        }
        if (c.isArray()){       //如果是数组
            String r = c.getComponentType()+"[]{\n";        //数组的元素的类型
            for (int i = 0; i < Array.getLength(obj); i++){
                if (i > 0){     //不是数组的第一个元素加逗号和换行，显示更加美观
                    r += ",\n";
                }
                r += "\t";
                Object val = Array.get(obj,i);
                if (c.getComponentType().isPrimitive()){        //Class为8种基本类型的时候为 true，直接输出
                    r += val;
                }else{
                    r += toString(val);     //不是8中基本类型时，说明是类，递归调用toString
                }
            }
            return r + "\n}";
        }

        //既不是String，也不是数组时，输出该对象的类型和属性值
        String r = c.getName();
        do{
            r += "[";
            Field[] fields = c.getDeclaredFields();     //获取该类自己定义的所有域，包括私有的，不包括父类的
            AccessibleObject.setAccessible(fields,true);        //访问私有的属性，需要打开这个设置，否则会报非法访问异常
            for (Field f : fields){
                if (!Modifier.isStatic(f.getModifiers())){      //通过 Modifier 可获取该域的修饰符，这里判断是否为 static
                    if (!r.endsWith("[")){
                        r += ",";
                    }
                    r += f.getName() + "=";
                    Class t = f.getType();
                    try {
                        Object val = f.get(obj);        //获取obj对象上该域的实际值
                        if (t.isPrimitive()){       //如果类型为8种基本类型，则直接输出
                            r += val;
                        }else {
                            r += toString(val);     //不是8种基本类型，递归调用toString
                        }
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
            r += "]";
            c = c.getSuperclass();      //继续打印超类的类信息
        }while (c != null);
        return r;
    }
}
